#include <iostream>
#include <sys/epoll.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <fcntl.h>

#include "socket.h"
#include "socketmanager.h"
#include "proto/message.pb.h"
#include "netmsgcenter.h"
#include "utils/encodetool.h"
#include "config.h"
#include "conf/serverconf.h"
#include "game/player.h"

#define MAX_EVENT_NUMBER 500
#define BUFFER_SIZE 4096

static Logger::ptr lvqiang = LoggerMgr::GetInstance()->GetLogger("lvqiang");

void et(epoll_event* events, int number, int epollfd, int server, NetMsgCenter::ptr& netMsgCenter)
{
    for(int i = 0; i < number; i++)
    {
        int socketfd = events[i].data.fd;
        Player::ptr player = PlayerMgr::GetInstance()->get(socketfd);
        if(player->GetSocket()->GetFd() == server)
        {
            struct sockaddr_in client_address;
            socklen_t client_addrlength = sizeof(client_address);
            int clientfd = accept(server, (struct sockaddr*)&client_address, &client_addrlength);
            Player::ptr player = PlayerMgr::GetInstance()->get(clientfd);
            player->GetSocket()->AddToEpoll(epollfd, true);
        }
        else if(events[i].events & EPOLLIN)
        {
            while (true)
            {
                int ret = player->GetSocket()->Receive();
                if(ret < 0)
                {
                    if((errno == EAGAIN) || (errno == EWOULDBLOCK))
                    {
                        LOG_INFO(lvqiang) << "接受一次数据完毕";
                        break;
                    }
                }
                else if(ret == 0)
                {
                    PlayerMgr::GetInstance()->del(socketfd);
                    player->GetSocket()->RemoveFromEpoll(epollfd);
                    break;
                }
                else
                {
                    proto::NetMsg netMsg;
                    EnCodeTool::DeCode(player->GetSocket()->GetRecvBuf(), netMsg);
                    netMsgCenter->dispacter(player, netMsg);
                }
            }
        }
    }
}

int main()
{
    //管理所有的连接
    SocketManager::ptr socketManager(new SocketManager());
    //消息处理分发中心
    NetMsgCenter::ptr netMsgCenter(new NetMsgCenter());
    //初始化配置
    ConfigMgr::GetInstance()->Init();
    ServerConf serverConf = ConfigMgr::GetInstance()->GetConfig<ServerConf>("ServerConf")->GetValue();

    Socket::ptr server = std::make_shared<Socket>();
    if(server->GetFd() < 0)
    {
        std::cout << "create server failed" << std::endl;
        return 0;
    }

    if(server->Bind(serverConf.GetIp().c_str(), serverConf.GetPort()) == -1)
    {
        std::cout << "bind failed" << errno << std::endl;
    }

    if(server->Listen(5) == -1)
    {
        std::cout << "listen failed" << std::endl;
    }

    epoll_event events[MAX_EVENT_NUMBER];
    int epollfd = epoll_create(5);
    if(epollfd == -1)
    {
        std::cout << "epollfd create failed" << std::endl;
    }
    server->AddToEpoll(epollfd, true);

    while(true)
    {
        int ret = epoll_wait(epollfd, events, MAX_EVENT_NUMBER, -1);
        if(ret < 0)
        {
            std::cout << "epoll_wait failed" << std::endl;
            break;
        }
        et(events, ret, epollfd, server->GetFd(), netMsgCenter);
    }

    close(epollfd);
    socketManager->del(server->GetFd());

    return 0;
}